/*global Ext,DocPanel,Docs,MainPanel, console, window  */

Ext.onReady(function () {
    var w = Ext.getCmp("welcome-panel");
    w.getUpdater().on('update', function () {
        var dh = Ext.DomHelper, 
            urlField;
        dh.append(
            Ext.getBody(), 
            {
                tag : 'div', 
                id  : 'my-proxy', 
                cls : 'x-hidden'
            }
        );
        dh.insertFirst(w.body.last().last(), {
            tag  : 'div',
            cls  : 'res-block',
            html : [
                '<div class="res-block-inner">', 
                '<h3>Compare with...</h3>', 
                '<div id="field-container"></div>', 
                '<p style="color:#666;line-height:20px;">Valid link to other Ext docs.</p>', 
                '</div>'
            ].join('')
        });
        urlField = new Ext.form.TextField({
            name     : 'diffUrl',
            id       : 'diffUrl',
            renderTo : 'field-container',
            width    : 185,
            value    : '../../ext-2.2.1/docs/'
        });
    });
});
Ext.override(MainPanel, {
    onClick : function (e, target) {
        var cls,
            member, 
            theLocation,
            tr;
        if (target = e.getTarget('a:not(.exi)', 3)) {
            cls = Ext.fly(target).getAttributeNS('ext', 'cls');
            e.stopEvent();
            if (cls) {
                member = Ext.fly(target).getAttributeNS('ext', 'member');
                // removes current location from target.href  {{{
                theLocation = target.href.replace(window.location.href.split('?')[0], '');
                // }}}
                this.loadClass(theLocation, cls, member);
            } else if (target.className === 'inner-link') {
                this.getActiveTab().scrollToSection(target.href.split('#')[1]);
            } else if (target.className === 'inner-member-link') {
                // scrolls to member {{{
                this.scrollToMember(target.href.split('#')[1]);
                // }}}
            } else {
                window.open(target.href);
            }
        } else if (target = e.getTarget('.micon', 4)) {
            e.stopEvent();
            tr = Ext.fly(target.parentNode);
            if (tr.hasClass('expandable')) {
                tr.toggleClass('expanded');
            }
        }
    },
    scrollToMember : function (member) {
        var el = Ext.fly(member),
            top;
        if (el) {
            top = (el.getOffsetsTo(this.body)[1]) + this.getActiveTab().body.dom.scrollTop;
            this.getActiveTab().body.scrollTo('top', top - 25, {duration : 0.75});
        }
    },
    loadClass : function (href, cls, member) {
        var id = 'docs-' + cls, tab = this.getComponent(id), autoLoad, p;
        if (tab) {
            this.setActiveTab(tab);
            if (member) {
                tab.scrollToMember(member);
            }
        } else {
            autoLoad = {url: href};
            if (member) {
                autoLoad.callback = function () {
                    Ext.getCmp(id).scrollToMember(member);
                };
            }
            p = this.add(new DocPanel({
                id: id,
                cclass : cls,
                autoLoad: autoLoad,
                iconCls: Docs.icons[cls]
            }));

            this.diffField = Ext.getCmp('diffUrl');
            this.diffUrl   = this.diffField.getValue();
            if (this.diffField && this.diffUrl) {
                p.on('render', function () {
                    p.getUpdater().on('update', function (body, result) {
                        this.loadPrevClass(href, p);
                    }, this);
                }, this);
            }
            this.setActiveTab(p);
        }
    },
    loadPrevClass: function (href, p) {
       
        Ext.Ajax.request({
            url     : this.diffUrl + href,
            scope   : this,
            success : this.compareDocs.createDelegate(this, [p], 1),
            failure : function () {
                this.addSection(
                    p.body.select('.hr').elements[0], 
                    this.sectionRow([
                        '<b style="color:#bb1100">Class is brand new!</b>',
                        '<div class="mdesc">Cannot compare. Class doc cannot be found.',
                        '.</div>'
                    ], false)
                );
            }
        });
    },
    compareDocs: function (res, p) {
        var pbody               = p.body,
            newies              = pbody.select('.sig'), 
            newPropTable        = pbody.select('table:prev(h1)').elements[0],
            newDescription      = pbody.select('.description').elements[0],
            classTitle          = pbody.select('h1 a').elements[0],
            hr                  = pbody.select('.hr').elements[0],
            tools               = pbody.select('.top-tools').elements[0],
            newInheritance      = pbody.select('.inheritance').elements[0],
            newInheritanceStr   = '<pre class="res-block-inner"></pre>',
            
            proxy               = Ext.get('my-proxy'), 
            oldies, 
            oldPropTable,
            oldDescription,
            oldInheritance,
            oldInheritanceStr   = '<pre class="res-block-inner"></pre>',
            
            oldStuff            = {},
            newStuff            = [],

            newItems            = [],
            missingItems        = [],
            changedItems        = [],

            howManyNew          = 0, 
            howManyMissing      = 0,
            howManyChanged      = 0,

            sectionArr          = [];

        proxy.update(res.responseText);
        oldies = proxy.select('.sig');
        oldPropTable = proxy.select('table:prev(h1)').elements[0]; 
        oldDescription = proxy.select('.description').elements[0];
        oldInheritance = proxy.select('.inheritance').elements[0];
            
        oldies.each(function (e) {
            // prepare oldStuff obj for easy check
            var theId = e.first('a').dom.id.split('-')[1];
            oldStuff[theId] = {
                pname       : theId,
                pid         : e.first('a').dom.id,
                pdesc       : e.first().next('.mdesc').dom.innerHTML,
                pall        : e.dom.innerHTML
            };
        });

        newies.each(function (e) {
            // prepare newStuff obj for easy check
            var theId = e.first('a').dom.id.split('-')[1];
            newStuff[theId] = {
                pname       : theId,
                pid         : e.first('a').dom.id,
                pdesc       : e.first().next('.mdesc').dom.innerHTML,
                pall        : e.dom.innerHTML
            };
            // check if oldStuff items are missing
            if (oldStuff[theId] === undefined) {
                howManyNew = howManyNew + 1;
                this.highlightItem(e.first('b').first());
                newItems.push('<li><a class="inner-member-link" href="#', newStuff[theId].pid, '">', newStuff[theId].pname, '</a></li>');
            // check if newies item differs from oldStuff[theId]
            } else {
                if (this.checkItems(e, oldStuff[theId])) {
                    howManyChanged = howManyChanged + 1;
                    changedItems.push('<li><a class="inner-member-link" href="#', newStuff[theId].pid, '">', newStuff[theId].pname, '</a></li>');
                }
            }
        }, this);

        oldies.each(function (e) {
            // one more iteration to collect missing items in newStuff
            var theId = e.first('a').dom.id.split('-')[1];
            if (newStuff[theId] === undefined) {
                howManyMissing = howManyMissing + 1;
                missingItems.push('<li><b>', oldStuff[theId].pname, '</b><br><div style="border:1px solid #D0D0D0;padding:10px">', oldStuff[theId].pdesc, '</div></li>');
            }
        }, this);

        if (typeof console === 'object') {
            console.info('New:', howManyNew);
            console.info('Missing:', howManyMissing);
            console.info('Changed:', howManyChanged);
        }

        // new items section row
        if (howManyNew > 0) {
            sectionArr.push(this.sectionRow([
                '<b>', howManyNew, (howManyNew === 1 ? ' New Item ': ' New Items '), '</b>', 
                '<div class="mdesc">New items are <span style="background:#083772;color:#ffffff;padding:2px">highlighted</span>. Expand to see the list.',
                '<div class="long"><ul style="list-style-type:disc;margin-left:15px;">',
                newItems.join(''),
                '</ul></div>',
                '<div>'
            ], true));
        } 

        // missing items section row
        if (howManyMissing > 0) {
            sectionArr.push(this.sectionRow([
                '<b>', howManyMissing, (howManyMissing === 1 ? ' Item ': ' Items '), ' Missing</b>',
                '<div class="mdesc">Expand to see the list.', 
                '<div class="long"><ul style="list-style-type:disc;margin-left:15px;">',
                missingItems.join(''),
                '</ul></div>',
                '<div>'
            ], true));
        } 

        // changed items section row
        if (howManyChanged > 0) {
            sectionArr.push(this.sectionRow([
                '<b>', 
                howManyChanged, 
                (howManyChanged === 1 ? ' Item ': ' Items '),
                ' Changed</b>',
                '<div class="mdesc">Changed items are marked by <span class="x-form-invalid" style="border:0;">red bottom border</span>. Expand to see the list.',
                '<div class="long">',
                '<ul style="list-style-type:disc;margin-left:15px;">',
                changedItems.join(''),
                '</ul>',
                '</div><div>'
            ], true));
        } 

        // class property table section row
        if (!this.compareItem(newPropTable.innerHTML, oldPropTable.innerHTML)) {
            sectionArr.push(this.sectionRow([
                '<b>Class Property table changed</b>', 
                '<div class="mdesc">Expand to see the details.',
                '<div class="long">',
                '<table border="0" cellpadding="2" cellspacing="0" align="left" style="margin-top:10px;border:1px solid #D0D0D0">',
                '<tr><th colspan="2">Previous at ', this.diffUrl, '</th></tr>',
                oldPropTable.innerHTML,
                '</table>',
                '<table border="0" cellpadding="2" cellspacing="0"  align="left" style="margin:10px 0px 0px 20px;border:1px solid #D0D0D0">',
                '<tr><th colspan="2">Current</th></tr>',
                newPropTable.innerHTML,
                '</table>',
                '</div></div>'
            ], true));
        }

        // class description section row
        if (!this.compareItem(newDescription.innerHTML, oldDescription.innerHTML)) {
            sectionArr.push(this.sectionRow([
                '<b>Class description has been changed</b>', 
                '<div class="mdesc">Expand to see the previous one.',
                '<div class="long">',
                '<table class="member-table" cellspacing="0" style="margin-top:10px;">', 
                '<tr><th class="sig-header">',
                'Class description at ', 
                this.diffUrl,
                '</th></tr>',
                '<tr><td class="sig" style="line-height:20px;padding-left:15px; background:#fafafa;">',
                oldDescription.innerHTML,
                '</td></tr>',
                '</table>',
                '</div></div>'
            ], true));
        }

        // class inheritance section row
        if (oldInheritance) {
            oldInheritanceStr = oldInheritance.innerHTML;
        }
        if (newInheritance) {
            newInheritanceStr = newInheritance.innerHTML;
        }
        if (!this.compareItem(oldInheritanceStr, newInheritanceStr)) {
            sectionArr.push(this.sectionRow([
                '<b>Class inheritance tree has been changed</b>', 
                '<div class="mdesc">Expand to see the details.',
                '<div class="long">',
                '<div class="long">',
                '<table border="0" cellpadding="2" cellspacing="0" align="left" style="margin-top:10px;border:1px solid #D0D0D0">',
                '<tr><th colspan="2">Previous at ', this.diffUrl, '</th></tr>',
                '<tr><td style="padding:0 15px 0 15px;"><div class="inheritance res-block">',
                oldInheritanceStr,
                '</div></td></tr>',
                '</table>',
                '<table border="0" cellpadding="2" cellspacing="0"  align="left" style="margin:10px 0px 0px 20px;border:1px solid #D0D0D0">',
                '<tr><th colspan="2">Current</th></tr>',
                '<tr><td style="padding:0 15px 0 15px;"><div class="inheritance res-block">',
                newInheritanceStr,
                '</div></td></tr>',
                '</table>',
                '</div></div>'
            ], true));
        }

        if (sectionArr) {
            this.addSection(hr, sectionArr.join(''), classTitle.innerHTML);
            this.addToolsLink(tools, classTitle.innerHTML);
        }
    },
    addToolsLink: function (el, className) {
        Ext.DomHelper.insertFirst(el, [
            '<a href="#', 
            className, 
            '-comparison" class="inner-link">', 
            '<img class="item-icon icon-cls" src="resources/images/default/s.gif"/>', 
            'Comparison info', 
            '</a>'
        ].join(''));
    },
    addSection: function (el, msg, className) {
        Ext.DomHelper.insertAfter(el, [
            '<a id="',
            className,
            '-comparison"></a>',
            '<h2>Comparison info</h2>',
            '<table class="member-table" cellspacing="0" style="clear:both;"><tbody>', 
            '<tr><th colspan="2" class="sig-header">When compared with the docs at ' + this.diffUrl + '.</th></tr>',
            msg,
            '</tbody></table>'
        ].join(''));
    },
    sectionRow: function (msg, expandable) {
        return ['<tr class="property-row', 
            expandable ? ' expandable' : '',
            '"><td class="micon"><a class="exi" href="#expand"> </a></td>', 
            '<td class="sig">',
            msg.join(''),
            '</td></tr>'].join('');
    },
    highlightItem: function (t) {
        t.applyStyles({
            background  : '#083772',
            color       : '#ffffff',
            padding     : '2px'
        });
    },
    checkItems: function (e, oldStuffItem) {
        var dh       = Ext.DomHelper,
            itemName = e.first().next(),
            longDesc = e.first('div').first('div.long'),
            toAppend = ['<div style="padding-top:10px"><table class="member-table" cellspacing="0" style="clear:both;"><tbody>', 
                '<tr><th colspan="1" class="sig-header">',
                'Item description at ', 
                this.diffUrl,
                '</th></tr>',
                '<tr class="expandable">',
                '<td class="sig" style="line-height:20px;padding-left:15px; background:#fafafa;">',
                oldStuffItem.pall,
                '</td></tr></tbody></table></div>'
                ].join('');


        if (!this.compareItem(e.dom.innerHTML, oldStuffItem.pall)) {
            itemName.addClass('x-form-invalid');
            itemName.applyStyles({border : '0'});
            if (longDesc) {
                dh.append(
                    longDesc || e.first('div'), 
                    toAppend
                );
            } else {
                Ext.fly(e.dom.parentNode).addClass('expandable');
                dh.append(
                    e.first('div'), 
                    ['<div class="long">', toAppend, '</div>'].join('')
                );
            }
            return true;
        }
        return false;
    },
    compareItem: function (a, b) {
        var format = Ext.util.Format,
            n = format.stripTags(a).replace(/(\s|&nbsp;?)/g, ''),
            o = format.stripTags(b).replace(/(\s|&nbsp;?)/g, '');
        return n === o;
    }
});